AWS IoT Device SDK for JavaScriptのサンプルでAWS IoTプログラミングを理解する #reinvent
ども、大瀧です。
AWSのカンファレンスイベント、re:Invent 2015で発表&ベータがローンチされたAWS IoT、皆さん触ってますか?
AWS IoTはメッセージブローカーを基盤とするIoTデバイスとAWSサービスを連携させるサービスです。今回ご紹介するAWS IoT Device SDKは、AWS IoTのMQTT APIと通信するためのラッパーライブラリです。現在、以下3つのプログラミング言語/プラットフォームの対応版が公開されています。
いずれも現時点でできることはさほど大きく変わりません。今回はJavaScript版を試してみたいと思います。
IoT Device SDKでできること
上述の通り、MQTTのマネージドサービスであるAWS IoTメッセージブローカーを介するPub/Subを実装します。AWS IoTでは純粋なPub/Subに加えて、デバイス(Thing)の属性情報をAWS IoT側で保持するRegistryとデバイスの状態情報をAWS IoT側で管理するThing Shadowsという機能がありますが、RegistryはREST APIのみで提供されるためDevice SDKでアクセスできるのはPub/SubとThing Shadowsのみです。
一方で、Thing Shadowsは前回のエントリーでご紹介した通り特定トピックへのPub/Subが実際には行われるのですが、トピックの階層を理解した上で複数トピックを組み合わせなければならないなど、プログラミングにおいて煩雑な要素が多いと見ることもできます。Device SDKは、Thing Shadowsに関するPub/Sub処理を抽象化することで見通しの良いコーディングをサポートするとともに、MQTTやPub/Subの知識があまり無いプログラマに対してはそれらの実装を隠蔽するはたらきを持ちます。
また、Device SDKと名付けられてはいますがハードウェアとしての制約は無いので、管理アプリケーションなどデバイス以外のマシンで利用することもできます。試してはいないですが、Lambdaでも動くかもしれません。
IoT Device SDK for JavaScriptのセットアップ
- 検証環境 : Vagrant/VirtualBox仮想マシン debian/wheezy
- aws-iot-device-sdkのバージョン : 1.0.2
まずは、以下のブログを参考に、Debian WheezyにNode.jsをインストールします。
$ sudo vi /etc/apt/sources.list # 以下を追加 deb http://ftp.jp.debian.org/debian/ wheezy-backports main contrib non-free deb-src http://ftp.jp.debian.org/debian/ wheezy-backports main contrib non-free $ sudo apt-get update :(略) $ sudo apt-get install nodejs nodejs-legacy :(略) $ curl -L https://npmjs.org/install.sh | sudo sh :(略) $
Node.jsのセットアップはこれでOKです。続いて、IoT Device SDKをインストールします。GitHubのREADME.mdにはnpm
でのインストールコマンドが書かれていますが、/index.js
のrequire
文がイマイチでnpm
環境では動きませんでした。git clone
で持ってきて、依存パッケージをインストールします。
$ sudo apt-get install g++ git # g++は依存パッケージのインストールのために必要 :(略) $ git clone https://github.com/aws/aws-iot-device-sdk-js.git :(略) $ cd aws-iot-device-sdk-js/ $ npm install mqtt $ npm install blessed $ npm install blessed-contrib $ npm install minimist
これで準備OKです。
サンプルプログラムの使い方
GitHubのREADME.mdにかなり詳しく関われていますので、詳細はそちらを参照して下さい。サンプルはexamples/
以下にいくつかあります。いずれのスクリプトも-h
オプションでヘルプが見られるので、実行する前に確認しましょう。MQTT APIにアクセスするためには、こちらのエントリーにあるクライアント証明書一式が必要です。Thing Shadowsを試すサンプルの場合はこちらのエントリーにあるようにThingを作成しておきましょう。
サンプルは以下があります。
- device-example.js : 端末を二つ用意し、
-t
オプションの1と2でお互いにPub/Subを繰り返します - echo-example.js :
-T
オプションで指定するThingの更新内容(delta)を表示するシンプルなサンプル - temperature-control.js : 端末を二つ用意し、温度管理についてのデバイスと管理アプリケーションのやり取りをシミュレーションします
- thing-example.js : 端末を二つ用意し、表示色についてのデバイスと管理アプリケーションのやり取りをシミュレーションします
ひとまず、device-example.js
を試してみましょう。まずはヘルプを確認します。
$ node examples/device-example.js -h Usage: device-example.js [OPTION...] device-example.js: connect to the AWS IoT service and publish/subscribe to topics using MQTT, test modes 1-2 Options -g, --aws-region=REGION AWS IoT region -i, --client-id=ID use ID as client ID -k, --private-key=FILE use FILE as private key -c, --client-certificate=FILE use FILE as client certificate -a, --ca-certificate=FILE use FILE as CA certificate -f, --certificate-dir=DIR look in DIR for certificates -r, --reconnect-period-ms=VALUE use VALUE as the reconnect period (ms) -t, --test-mode=[1-n] set test mode for multi-process tests -T, --thing-name=THINGNAME access thing shadow named THINGNAME -d, --delay-ms=VALUE delay in milliseconds before publishing Default values aws-region us-east-1 client-id $USER<random-integer> private-key ./privkey.pem client-certificate ./cert.pem ca-certificate ./aws-iot-rootCA.crt reconnect-period-ms 3000ms delay-ms 4000ms test-mode 1
今回は東京リージョンのエンドポイントを利用したいので-g
オプション、証明書は-k
/-c
/-a
オプションでそれぞれ設定できますが、証明書一式をデフォルトのファイル名で用意し、-f
オプションで指定するのが楽でしょう。
$ node examples/device-example.js -f /vagrant -g ap-northeast-1 -t 1 connect message topic_1 {"mode_2_process":1} :
$ node examples/device-example.js -f /vagrant -g ap-northeast-1 -t 2 connect message topic_2 {"mode_1_process":17} :
1つ目の端末はtopic_2にメッセージをPublishしつつtopic_1をSubcribeし、2つ目の端末は逆にtopic_2をSubscribeしつつtopic_1にメッセージをPublishしていることがわかりますね。ではソースを見てみましょう。
21行目でDevice SDKのdeviceモジュールを読み込み、33〜40行目でモジュールで定義されるDeviceクラスからインスタンスを生成しています。
: 21 const deviceModule = require('../device'); : 33 const device = deviceModule({ 34 keyPath: args.privateKey, 35 certPath: args.clientCert, 36 caPath: args.caCert, 37 clientId: args.clientId, 38 region: args.region, 39 reconnectPeriod: args.reconnectPeriod, 40 }); :
生成したdeviceインスタンスはMQTTの処理をラップし、対応するトピックのパスや実行するタイミングをイベントリスナーとして定義します。50行目以降はひたすらリスナーを定義しているのがわかります。
50 device 51 .on('connect', function() { : : 80 }); 81 device 82 .on('close', function() { 83 console.log('close'); 84 clearInterval( timeout ); 85 count=0; 86 }); :
Deviceクラスはmqtt.Clientクラスを薄くラップしただけでイベントは全てmqtt.Clientクラスと共通です。一方、Thing Shadowsを扱うためのThingShadowクラスのインスタンスは以下のイベントリスナーを定義しつつ、メソッドをコールしてThingおよびThing Shadowの操作を行います。
- deltaイベント : ThingとThing Shadowの差分ができた時に発生する。デバイス側で実装し、差分に合わせた処理を実行し、Thingの状態を更新する
- statusイベント : Thing/Thing Shadowの変更リクエストが受理された時に発生する
- timeoutイベント : Thing/Thing Shadowの変更リクエストがタイムアウトした時に発生する
この辺りの実装例としてはthing-example.js
が参考になるでしょう。
実際に作成するときは
Device SDKとしては、MQTTブローカーへのPub/Subのみ利用する場合とPub/SubとThing Shadowsを併用する2パターンが考えられます。デバイスからクラウドに一方向にデータを送信するようなシンプルなセンサーネットワークであればPub/Subのみで十分なこともあると思います。一方、Thing Shadowsを利用することで管理アプリケーションからのデバイス操作に関するメッセージングが可能にあるため、HEMS用途やデバイスの遠隔操作などに利用することができるでしょう。
まとめ
AWS IoT Device SDKのサンプルをご紹介しました。AWS IoTを利用するIoTシステムでのプログラミングの雰囲気が少しでも伝われば嬉しいです。